package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.domain.Category;
import com.itheima.domain.Setmeal;
import com.itheima.dao.SetmealDao;
import com.itheima.domain.SetmealDish;
import com.itheima.dto.SetmealDto;
import com.itheima.exception.DeleteSetMealException;
import com.itheima.service.CategoryService;
import com.itheima.service.SetmealDishService;
import com.itheima.service.SetmealService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealDao, Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishService setmealDishService;

    @Autowired
    private CategoryService categoryService;

    @Override
    @Transactional
    public void saveWithDish(SetmealDto setmealDto) {
        /**
         * 新增套餐
         * 从前端传过来的参数，包含两部分：
         * 1.套餐信息-->保存到套餐表（setmeal）
         * 2.套餐包含的菜品信息-->保存到关联表（setmeal_dish）
         * 因此我们用setmealdto来封装数据
         */

        //1.保存到套餐表（setmeal）
        this.save(setmealDto);

        /**
         * setmealDto中的setmealDishes属性，就是前端传过来的菜品的信息
         * 遍历集合，一条一条的写入关联表即可
         * 关联表中的setmeal_id 字段，需要我们手动写入（雪花算法自动生成，从setmealdto中直接拿即可）
         */
        //2.保存到关联表
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        for (SetmealDish setmealDish : setmealDishes) {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDishService.save(setmealDish);
        }
    }

    @Override
    public Page getPageWithGategory(int page, int pageSize, String name) {
        /**
         * 分页查询
         * 除了要展示套餐表的所有内容，还要展示套餐所属分类的名字
         * 因此，要查两张表
         * 最终把所有数据，封装到dto中，返回给前端
         */

        Page<Setmeal> pageinfo = new Page<>(page, pageSize);
        LambdaQueryWrapper<Setmeal> lqw = new LambdaQueryWrapper<>();
        lqw.like(name != null, Setmeal::getName, name);
        lqw.orderByDesc(Setmeal::getUpdateTime);
        this.page(pageinfo, lqw);

        List<Setmeal> records = pageinfo.getRecords();
        List<SetmealDto> list = new ArrayList<>();

        for (Setmeal record : records) {
            Long categoryId = record.getCategoryId();
            Category category = categoryService.getById(categoryId);

            SetmealDto setmealDto = new SetmealDto();
            BeanUtils.copyProperties(record, setmealDto);
            setmealDto.setCategoryName(category.getName());
            list.add(setmealDto);
        }

        Page<SetmealDto> setmealDtoPage = new Page<>();
        BeanUtils.copyProperties(pageinfo, setmealDtoPage);
        setmealDtoPage.setRecords(list);
        return setmealDtoPage;
    }

    @Override
    @Transactional
    public void delete(List<Long> ids) {
        /**
         * 删除套餐，
         * 先确定下套餐的状态，如果正在售卖，就提示无法删除，请先停用
         * 如果是停用状态，就接着检查该套餐有无关联菜品
         * 如果关联了菜品，就先去关联表，把关联信息全部删除，最后删除套餐
         */

        //1.查询不符合删除条件的个数
        LambdaQueryWrapper<Setmeal> lqw1 = new LambdaQueryWrapper<>();
        lqw1.in(Setmeal::getId, ids);
        lqw1.eq(Setmeal::getStatus, 1);
        int count = this.count(lqw1);

        //count就是状态为1（起售状态）的个数
        if (count > 0) {
            throw new DeleteSetMealException("请先全部停售，再删除");
        }

        //走到这里，说明全部是都停用状态，都可以删除
        //先删除套餐表的数据
        this.removeByIds(ids);

        //删除关联表中的数据
        LambdaQueryWrapper<SetmealDish> lqw2 = new LambdaQueryWrapper<>();
        lqw2.in(SetmealDish::getSetmealId, ids);
        setmealDishService.remove(lqw2);
    }

    @Override
    public void soldAndStop(List<Long> ids) {
        LambdaQueryWrapper<Setmeal> lqw1 = new LambdaQueryWrapper<>();
        lqw1.in(Setmeal::getId, ids);
        List<Setmeal> list = this.list(lqw1);

        for (Setmeal setmeal : list) {
            if (setmeal.getStatus() == 1) {
                setmeal.setStatus(0);
            } else {
                setmeal.setStatus(1);
            }

            LambdaQueryWrapper<Setmeal> lqw2 = new LambdaQueryWrapper<>();
            lqw2.eq(Setmeal::getId, setmeal.getId());
            this.update(setmeal, lqw2);
        }
    }

    @Override
    public SetmealDto selectById(Long id) {
        /**
         * 信息回显
         * 1.拿到套餐自身的信息
         * 2.拿到套餐关联的菜品的信息
         */

        //1.拿到套餐信息
        Setmeal setmeal = this.getById(id);

        //2.拿关联的菜品的信息
        LambdaQueryWrapper<SetmealDish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SetmealDish::getSetmealId,id);
        List<SetmealDish> list = setmealDishService.list(lqw);

        //3.把数据都封装到SetmealDto中，返回给页面
        SetmealDto setmealDto = new SetmealDto();
        BeanUtils.copyProperties(setmeal,setmealDto);
        setmealDto.setSetmealDishes(list);
        return setmealDto;

    }

    @Override
    @Transactional
    public void updateWithDish(SetmealDto setmealDto) {
        /**
         * 保存修改后的信息
         * 写入套餐表
         * 写入关联表
         */

        //1.修改套餐表
        this.updateById(setmealDto);

        //2.把关联表中的原数据删除
        LambdaQueryWrapper<SetmealDish> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SetmealDish::getSetmealId,setmealDto.getId());
        setmealDishService.remove(lqw);

        //3.把新的数据写入关联表
        //集合中装的就是所有的菜品数据
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        for (SetmealDish setmealDish : setmealDishes) {
            setmealDish.setSetmealId(setmealDto.getId());
            setmealDishService.save(setmealDish);
        }
    }
}